package com.smasher.nfc

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.nfc.NdefMessage
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.IsoDep
import android.nfc.tech.MifareClassic
import android.nfc.tech.Ndef
import android.nfc.tech.NdefFormatable
import android.nfc.tech.NfcA
import android.nfc.tech.NfcB
import android.nfc.tech.NfcF
import android.nfc.tech.NfcV
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.smasher.nfc.protocol.mifare.MifareHelper
import com.smasher.nfc.protocol.ndef.NdefHelper
import com.smasher.nfc.protocol.nfcv.NfcVHelper
import com.smasher.nfc.util.VibrationHelper
import java.io.UnsupportedEncodingException
import java.nio.charset.StandardCharsets
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

abstract class NFCAction : NFCConfig() {

    private val ndefHelper = NdefHelper { success, message -> 
        showToast(message)
        if (success) {
            doVibrate()
        }
    }

    private val nfcVHelper = NfcVHelper()
    private val mifareHelper = MifareHelper()

    private val executorService: ExecutorService = Executors.newSingleThreadExecutor()

    // 添加 Handler 来切换到主线程
    private val handler: Handler = Handler(Looper.getMainLooper())

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        readTag()
    }

    //当该Activity接收到NFC标签时，运行该方法
    fun readTag() {
        if (mNfcAdapter == null) {
            showToast("请检查并打开NFC")
            return
        }
        val action = intent.action

        when (action) {
            NfcAdapter.ACTION_TAG_DISCOVERED -> {
                Log.d(TAG, "action: TAG_DISCOVERED")
            }

            NfcAdapter.ACTION_NDEF_DISCOVERED -> {
                Log.d(TAG, "action: NDEF_DISCOVERED")
            }

            NfcAdapter.ACTION_TECH_DISCOVERED -> {
                Log.d(TAG, "action: TECH_DISCOVERED")
            }

            else -> {
                Log.d(TAG, "action: unknown ")
            }
        }

        executorService.execute {
            try {
                val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)

                val id = readTagId(tag)
                Log.d(TAG, "tagId: $id")
                // 切换到主线程执行回调
                handler.post { onReadId(id) }

                val uid = readTagUID(tag)
                // 切换到主线程执行回调
                handler.post { onReadUId(uid) }

                val techList = readTechList(tag)
                Log.d(TAG, "techList: " + techList.contentToString())
                // 切换到主线程执行回调
                handler.post { onReadSupportTech(techList) }

                Log.i(TAG, "================Support start================")

                if (techList.contains(NdefFormatable::class.java.name)) {
                    Log.i(TAG, "support NdefFormatable")
                }

                if (techList.contains(NfcA::class.java.name) ||
                    //ISO 14443-3A ##NfcA
                    techList.contains(NfcB::class.java.name) ||
                    //ISO 14443-3B ##NfcB
                    techList.contains(NfcF::class.java.name) ||
                    //JIS 6319-4 ##NfcF
                    techList.contains(IsoDep::class.java.name)
                //ISO 14443-4 ##IsoDep
                ) {
                    Log.i(TAG, "暂不支持的协议")
                }

                if (techList.contains(Ndef::class.java.name)) {
                    Log.i(TAG, "support Ndef")
                    //NDEF #Ndef
                    if (tag != null) {
                        readNdef(tag, intent)
                    }
                }

                if (techList.contains(NfcV::class.java.name)) {
                    Log.i(TAG, "support NfcV")
                    //ISO 15693 ##NfcV
                    //showToast("NfcV协议")
                    if (tag != null) {
                        nfcVHelper.readNfcV(tag)
                    }
                }

                if (techList.contains(MifareClassic::class.java.name)) {
                    Log.i(TAG, "support MifareClassic")
                    if (tag != null) {
                        mifareHelper.readMifareClassic(tag)
                    }
                }
                Log.i(TAG, "================Support end================")

            } catch (e: Exception) {
                Log.e(TAG, "readTag: ", e)
                showToast("读取标签失败，请重试")
            }
        }
    }

    /**
     * 读取ID
     */
    private fun readTagId(tag: Tag?): String? {
        return tag?.id?.let { byteArrayToHexString(it) }
    }

    /**
     * 读取UID
     */
    private fun readTagUID(tag: Tag?): String? {
        var uId: String? = null
        try {
            uId = tag?.id?.let { bytes -> 
                byteArrayToHexString(bytes.reversedArray())
            }
        } catch (e: Exception) {
            Log.e(TAG, "readNfcUID: ", e)
        }
        return uId
    }

    /**
     * 读取TechList
     */
    private fun readTechList(tag: Tag?): Array<String> {
        return tag?.techList?.toList()?.toTypedArray() ?: emptyArray()
    }

//=====================================================================

    /**
     * 读取Ndef 数据
     */
    private fun readNdef(tag: Tag, intent: Intent) {
        //NDEF #Ndef
        val ndef = Ndef.get(tag) ?: return // NDEF is not supported by this Tag.

        val type = ndef.type
        Log.d(TAG, "ndef type:$type ")
        val str = readNdefMessageFromIntent(intent)
        Log.d(TAG, "content: ${str.contentToString()}")
        val result = if (!str.isNullOrEmpty()) {
            handler.post { onReadNdefMessages(str) } // 切换到主线程执行回调
            val temp0 = str[0]
            val defaultValue = readNdefRecordDefault(temp0)
            defaultValue
        } else {
            ""
        }
        if (!TextUtils.isEmpty(result)) {
            handler.post { onReadNdef(result) } // 切换到主线程执行回调
        }

        val ndefMessage = ndef.cachedNdefMessage
        val records = ndefMessage.records
        for (ndefRecord in records) {
            val payload = ndefRecord.payload
            // 处理payload数据
            val payloadValue = readDataFromPayload(payload)
            Log.d(TAG, "ndefRecord: $payloadValue")
        }
    }


    /**
     * 读取NFC Ndef的数据
     */
    private fun readNdefMessageFromIntent(intent: Intent): Array<NdefMessage>? {
        val rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES) ?: return null
        val length = rawArray.size

        val list = ArrayList<NdefMessage>()
        for (index in 0 until length) {
            try {
                val ndefMessage = rawArray[index] as NdefMessage
                list.add(ndefMessage)
            } catch (e: Exception) {
                Log.e(TAG, "readNdefMessageFromIntent: ${e.message}")
            }
        }
        return list.toTypedArray()
    }

    /**
     * 读取NFC Ndef Payload的数据
     */
    private fun readNdefRecordDefault(mNdefMsg: NdefMessage): String {
        var readResult = ""
        val mNdefRecord = mNdefMsg.records[0]
        if (mNdefRecord != null) {
            val payload = mNdefRecord.payload
            readResult = readDataFromPayload(payload)
            return readResult
        }
        return ""
    }

    /**
     * 解析NFC Ndef数据
     */
    private fun readDataFromPayload(payload: ByteArray): String {
        val readResult: String
        val textEncoding = if (payload[0].toInt() and 0x80 == 0) "UTF-8" else "UTF-16"
        //处理bit5-0。bit5-0表示语言编码长度（字节数）
        val languageCodeLength = payload[0].toInt() and 0x3f
        //获取语言编码（从payload的第2个字节读取languageCodeLength个字节作为语言编码）
        val languageCode = String(
            payload, 1, languageCodeLength,
            StandardCharsets.US_ASCII
        )
        //解析出实际的文本数据
        readResult = try {
            String(
                payload, languageCodeLength + 1,
                payload.size - languageCodeLength - 1, charset(textEncoding)
            )
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
            String(payload, StandardCharsets.UTF_8)
        }
        return readResult
    }


    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }

    @SuppressLint("MissingPermission")
    fun doVibrate() {
        val result = ActivityCompat.checkSelfPermission(this, Manifest.permission.VIBRATE)
        if (result == PackageManager.PERMISSION_GRANTED) {
            VibrationHelper(this).doVibration()
        }
    }

    /**
     * 将字节数组转换为字符串
     */
    private fun byteArrayToHexString(inarray: ByteArray): String {
        var out = ""
        var i: Int
        var j: Int = 0
        val hex = 
            arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
        var ln: Int
        while (j < inarray.size) {
            ln = inarray[j].toInt() and 0xff
            i = ln shr 4 and 0x0f
            out += hex[i]
            i = ln and 0x0f
            out += hex[i]
            ++j
        }
        return out
    }

//========================================================================

    /**
     * 写入 ndef数据
     * 写入文本
     */
    fun writeTag(data: String) {
        if (mNfcAdapter == null) {
            showToast("请检查并打开NFC")
            return
        }

        //nfc功能打开了
        if (mNfcAdapter?.isEnabled == true) {
            val intent = intent
            val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
            if (tag != null) {
                ndefHelper.writeTag(tag, data)
            }
        } else {
            showToast("请打开NFC后重试")
        }
    }

    //=======================================================================================


    open fun onReadId(id: String?) {

    }

    open fun onReadUId(id: String?) {

    }

    open fun onReadSupportTech(array: Array<String>) {

    }

    open fun onReadNdef(message: String) {

    }

    open fun onReadNdefMessages(array: Array<NdefMessage>) {

    }

    override fun onDestroy() {
        super.onDestroy()
        executorService.shutdown()
        nfcVHelper.release()
    }

    companion object {
        const val TAG = "ACTION"

    }
}